package org.teamh.gui.lobby;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.teamh.connection.MapDownload;
import org.teamh.connection.handler.ConnectionHandler;
import org.teamh.connection.refresh.RefreshLobby;
import org.teamh.gui.GUI;
import org.teamh.gui.createGame.CreateGameController;
import org.teamh.gui.createGame.CreateGameScreen;
import org.teamh.gui.createGame.ErrorPopup;
import org.teamh.logic.lobby.Game;
import org.teamh.logic.lobby.Player;
import org.teamh.logic.lobby.Team;

import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyEventSubscriber;
import de.lessvoid.nifty.controls.ListBox;
import de.lessvoid.nifty.controls.ListBoxSelectionChangedEvent;
import de.lessvoid.nifty.controls.TextField;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.elements.render.TextRenderer;
import de.lessvoid.nifty.elements.tools.TextBreak;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.screen.KeyInputHandler;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.lessvoid.nifty.tools.Color;

public class LobbyController implements ScreenController {

	private GUI gui;
	private Screen screen;
	private RefreshLobby refreshLobby;
	private ListBox<TextRenderer> chatBox;
	private Nifty nifty;
	private Element playerBox;
	private PlayerBoxController playerBoxController;
	private LinkedList<String> receiver;
	private int receiverToShow;
	private Color blue;
	private Color orange;
	private ListBox<GameEntryModel> gameBox;
	private GameBoxController gameBoxController;
	private CreateGameController createGameController;
	private CreateGameScreen createGameScreen;
	private boolean errorOccured;
	private ErrorPopup errorPopup;
	
	public LobbyController(GUI gui) {
		this.gui = gui;
	}

	public void logout() {
		clear();
		gui.setFollowingScreen(gui.getLoginScreen());
		gui.getStart().getConnection().sendMessage("LOGOUT");
		gui.getStart().getConnection().reconnect();
	}

	public void joinGame(){
		if ((screen.findNiftyControl("gamesBox",
		 ListBox.class).getFocusItem()) != null) {
			
			final String gameName = ((GameEntryModel) screen.findNiftyControl("gamesBox",
					ListBox.class).getFocusItem()).getName();
		 
			final String mapName = ((GameEntryModel) screen.findNiftyControl("gamesBox",
					ListBox.class).getFocusItem()).getMap();
			
			final String status = ((GameEntryModel) screen.findNiftyControl("gamesBox",
					ListBox.class).getFocusItem()).getStatus();
			
			if (status.equals("RUNNING")) {
				return;
			}
			
			clear();
			
			gui.setFollowingScreen(gui.getLoadingScreen());
			gui.getStart().getModel().setManagerReady(false);
			
			new Thread(new Runnable() {
				@Override
				public void run() {
					if(!(gui.getStart().getConnection().getMessageReceiver() instanceof ConnectionHandler)) {
						return;
					}
					
					ConnectionHandler connectionHandler = (ConnectionHandler)gui.getStart().getConnection().getMessageReceiver();
					connectionHandler.getMapDownload().downloadMap(mapName);
					connectionHandler.getMapDownload().waitForDownload();
				 
					gui.getStart().getConnection().sendMessage("JOIN GAME " + gameName);
				 
					File f = connectionHandler.getMapDownload().getPicture();
					gui.getIngameScreen().getIngameFunctions().getMap().setTextureFile(f);
				 		
					while (!gui.getStart().getModel().isManagerReady()) {
						try {
							Thread.sleep(20);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					
					gui.setFollowingScreen(gui.getIngameScreen());
				}
			}).start();
		}
		
	}
	
	public void kiJoinGame(final String gameName){
			
			clear();
			
			gui.setFollowingScreen(gui.getLoadingScreen());
			
			new Thread(new Runnable() {
				@Override
				public void run() {
					String mapName = "";
					gui.getStart().getModel().setManagerReady(false);
					
					for (Game g : gui.getStart().getModel().getGames()) {
						if (g.getName().equals(gameName)) {
							mapName = g.getMap();
						}
					}
					
					if(!(gui.getStart().getConnection().getMessageReceiver() instanceof ConnectionHandler)) {
						return;
					}
					
					ConnectionHandler connectionHandler = (ConnectionHandler)gui.getStart().getConnection().getMessageReceiver();
					
					connectionHandler.getMapDownload().downloadMap(mapName);
					connectionHandler.getMapDownload().waitForDownload();
				 
					gui.getStart().getConnection().sendMessage("JOIN GAME " + gameName);
				 
					File f = connectionHandler.getMapDownload().getPicture();
					gui.getIngameScreen().getIngameFunctions().getMap().setTextureFile(f);
				 		
					while (!gui.getStart().getModel().isManagerReady()) {
						try {
							Thread.sleep(20);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					
					gui.getStart().getModel().setManagerReady(false);
					gui.setFollowingScreen(gui.getIngameScreen());
				}
			}).start();
		
	}

	public void createGame() {
		createGameScreen.showScreen();
	}

	public void sendMessage() {
		
		TextField textField = screen.findNiftyControl("chatMessagesField",
				TextField.class);
		String message = textField.getText();

		textField.setText("");
		if (playerBoxController.getRedMarked() != null) {
			playerBoxController.clearColor();
		}
		
		if (message.startsWith("#startKI")) {
			String[] str = message.split(" ");
			if (str.length < 2) {
				return;
			}
			String gameName = str[1].substring(1);
			boolean view = false;
			if (str.length > 2) {
				if (str[2].substring(1).equals("y")) {
					view = true;
				}
			}
			gui.getStart().getModel().setView(view);
			gui.getStart().getModel().setGameName(gameName);
			gui.getStart().getConnection().sendMessage("create testplayer");
		} else if (message.startsWith("@SE") || message.startsWith("@Other")
				|| message.startsWith("@Team-")) {
			String[] str = message.split(" ");
			String receiver = str[0].substring(1);
			String chatmessage = "";

			if (this.receiver.contains("@" + receiver + " ")) {
				this.receiver.remove("@" + receiver + " ");
			}
			this.receiver.add(this.receiver.size() - 1, "@" + receiver + " ");
			receiverToShow = this.receiver.size() - 1;

			if (str.length > 1) {
				chatmessage += str[1];
				int i = 2;
				while (i < str.length) {
					chatmessage += " " + str[i];
					i++;
				}
				for (Team team : getPlayerInTeam()) {
					if (receiver.equals(team.getTeamName())) {
						if (!receiver.equals(gui.getStart().getModel()
								.getTeam())) {
							fillChatBox(gui.getStart().getModel()
									.getPlayerName()
									+ " -> " + receiver + ": " + chatmessage,
									orange.getColorString());
						}
						gui.getStart()
								.getConnection()
								.sendMessage(
										"MSG TEAM " + receiver + " "
												+ chatmessage);
					}
				}
			}
		} else if (message.startsWith("@")) {
			String[] str = message.split(" ");
			String receiver = str[0].substring(1);
			String chatmessage = "";

			if (this.receiver.contains("@" + receiver + " ")) {
				this.receiver.remove("@" + receiver + " ");
			}
			this.receiver.add(this.receiver.size() - 1, "@" + receiver + " ");
			receiverToShow = this.receiver.size() - 1;

			if (str.length > 1) {
				chatmessage += str[1];
				int i = 2;
				while (i < str.length) {
					chatmessage += " " + str[i];
					i++;
				}

				for (Player player : gui.getStart().getModel().getPlayers()) {
					if ((!receiver.equals(gui.getStart().getModel()
							.getPlayerName()))
							&& receiver.equals(player.getName())) {
						fillChatBox(gui.getStart().getModel().getPlayerName()
								+ " -> " + receiver + ": " + chatmessage, blue.getColorString());
						gui.getStart()
								.getConnection()
								.sendMessage(
										"MSG USER " + receiver + " "
												+ chatmessage);
					}
				}
			}
		} else {
			gui.getStart().getConnection().sendMessage("MSG ALL " + message);
		}

	}

	public void fillChatBox(String message, String color) {
		TextBreak newMessage = new TextBreak(message, chatBox.getWidth() - 25,
				nifty.getRenderEngine().getFont());
		List<String> text = newMessage.split();
		List<TextRenderer> coloredText = new ArrayList<TextRenderer>();
		for (String s : text) {
			coloredText.add(new TextRenderer(nifty, nifty.getRenderEngine()
					.getFont(), s));
		}
		for (TextRenderer t : coloredText) {
			t.setColor(new Color(color));
		}
		chatBox.addAllItems(coloredText);

		chatBox.showItemByIndex(chatBox.getItems().size() - 1);
	}

	@Override
	public void onStartScreen() {
		nifty.getNiftyMouse().resetMouseCursor();
		
		refreshLobby = new RefreshLobby(gui.getStart());
		refreshLobby.start();

		addKeyboardListenerTo("chatMessagesField");

		screen.findNiftyControl("chatMessagesField", TextField.class)
				.setFocus();
	}

	private void addKeyboardListenerTo(String elementName) {
		screen.findElementByName(elementName).addInputHandler(
				new KeyInputHandler() {
					@Override
					public boolean keyEvent(NiftyInputEvent inputEvent) {
						if (inputEvent == null)
							return false;
						switch (inputEvent) {
						case SubmitText:
							sendMessage();
							return true;
						case MoveCursorUp:
							showPrevReceiver();
							return true;
						case MoveCursorDown:
							showNextReceiver();
							return true;
						default:
							break;
						}
						return false;
					}
				});

	}

	private void showNextReceiver() {
		TextField textField = screen.findNiftyControl("chatMessagesField",
				TextField.class);

		if (this.receiver.size() > 1) {
			receiverToShow++;
			if (receiverToShow >= this.receiver.size()) {
				receiverToShow = this.receiver.size() - 1;
			}
			String receiver = this.receiver.get(receiverToShow);
			textField.setText(receiver);
			textField.setCursorPosition(textField.getText().length());
		}
	}

	private void showPrevReceiver() {
		TextField textField = screen.findNiftyControl("chatMessagesField",
				TextField.class);

		if (this.receiver.size() > 1) {
			receiverToShow--;
			if (receiverToShow < 0) {
				receiverToShow = 0;
			}
			String receiver = this.receiver.get(receiverToShow);
			textField.setText(receiver);
			textField.setCursorPosition(textField.getText().length());
		}
	}

	public void checkForUpdatePlayerInTeamList(LinkedList<Player> newPlayerList) {
		playerBoxController.updatePlayerInTeamList(newPlayerList);
	}

	@SuppressWarnings("unchecked")
	@Override
	public void bind(Nifty nifty, Screen screen) {
		this.nifty = nifty;
		this.screen = screen;
		chatBox = screen.findNiftyControl("chatBox", ListBox.class);
		playerBox = screen.findElementByName("playerBox");
		gameBox = screen.findNiftyControl("gamesBox", ListBox.class);
		playerBoxController = new PlayerBoxController(this);
		gameBoxController = new GameBoxController(this);
		createGameScreen = new CreateGameScreen(this);
		createGameController = new CreateGameController(this);
		errorPopup = new ErrorPopup(gui);
		receiver = new LinkedList<String>();
		receiver.add("");
		receiverToShow = 0;
		blue = new Color(0, 0, 1, 1);
		orange = new Color(1, 0, 0, 1);
		
		chatBox.setListBoxViewConverter(new ChatListBoxViewConverter());
		gameBox.setListBoxViewConverter(new GameBoxViewConverter());
	}

	@Override
	public void onEndScreen() {
		screen.findNiftyControl("chatMessagesField", TextField.class).setText(
				"");
		gui.getLobbyScreen().getLobbyController().getRefreshLobby().shutdown();
	}

	public void showTeamMember(String name) {
		playerBoxController.showTeamMember(name);
	}

	public void fillMessageBoxWithName(String name) {
		playerBoxController.fillMessageBoxWithName(name);
	}

	public RefreshLobby getRefreshLobby() {
		return refreshLobby;
	}

	public ArrayList<Team> getPlayerInTeam() {
		return playerBoxController.getPlayerInTeam();
	}

	public Screen getScreen() {
		return screen;
	}

	public Nifty getNifty() {
		return nifty;
	}
	
	public GUI getGui() {
		return gui;
	}

	public Element getPlayerBox() {
		return playerBox;
	}

	public void checkForUpdateGameList(LinkedList<Game> newGameList) {
		gameBoxController.checkForUpdateGameList(newGameList);
	}
	
	public ListBox<GameEntryModel> getGameBox() {
		return gameBox;
	}
	
	public CreateGameScreen getCreateGameScreen() {
		return createGameScreen;
	}

	
	//CREATECONTROLLERMETHODEN
	

	public void changeVisibility(String showname,String hidename) {
	   createGameController.changeVisibility(showname,hidename);
	}
	
		public void hideAllTexfieldEffects() {
	    createGameController.hideAllTexfieldEffects();
	}
	public void hide(String hidename) {
		createGameController.hide(hidename);
	}
	public void show(String showname) {
		createGameController.show(showname);
	}


	//Hoveraktionen
		public void showInformationtext(String name){
			createGameController.showInformationtext(name);
		}

		public void showInformationtextAndHovereffect(String name){//name wird �bergeben und dann der entsprechende name des informationstextes und des rahmens zusammengebaut und mit diesem namen dann die entsprechende funktion aufgerufen
			createGameController.showInformationtextAndHovereffect(name);
		}
	//Ende Hoveraktionen	
		public void hideAllInformationtexts(){
			createGameController.hideAllInformationtexts();
		}
		public void hideAllInformationtextsAndHovereffekts(){
			createGameController.hideAllInformationtextsAndHovereffekts();
		}

		public void hideAllBordersClicked(){
			createGameController.hideAllBordersClicked();
		}
		//Festlegen der Panelclickactionen Image2Players/Image3Players/Image4Players
		public void image2Playersclick(){
			createGameController.image2Playersclick();
		}
		public void image3Playersclick(){
			createGameController.image3Playersclick();
		}
		public void image4Playersclick(){
			createGameController.image4Playersclick();
		}
		
		//ENDE Festlegen der Panelclickactionen Image2Players/Image3Players/Image4Players
		
		//mapPreviewclickMethode
		public void mapPreviewclick(){
			createGameController.mapPreviewclick();
		}
		//ENDE mapPreviewclickMethode
		
		//startButtonclickMethode
		public void startButtonclick(){
			createGameController.createGameButtonclick();
			
		}
		//ENDE startButtonclickMethode
	public void backToLobby() {
		createGameController.backToLobby();
	}
//BOOOOOOOOOOOOTS	
	//Hoveraktionen
	public void showInformationtextBots(String name){
		createGameController.showInformationtextBots(name);
	}

	public void showInformationtextAndHovereffectBots(String name){//name wird �bergeben und dann der entsprechende name des informationstextes und des rahmens zusammengebaut und mit diesem namen dann die entsprechende funktion aufgerufen
		createGameController.showInformationtextAndHovereffectBots(name);
	}
//Ende Hoveraktionen	
	public void hideAllInformationtextsBots(){
		createGameController.hideAllInformationtextsBots();
	}
	public void hideAllInformationtextsAndHovereffektsBots(){
		createGameController.hideAllInformationtextsAndHovereffektsBots();
	}

	public void hideAllBordersClickedBots(){
		createGameController.hideAllBordersClickedBots();
	}
	
	public void createGameButtonclick() {
		createGameController.createGameButtonclick();
	}

	//Festlegen der Panelclickactionen Image2Players/Image3Players/Image4Players
	public void imageNoBotsclick(){
		createGameController.imageNoBotsclick();
	}
	public void image1Botsclick(){
		createGameController.image1Botsclick();
	}
	public void image2Botsclick(){
		createGameController.image2Botsclick();
	}
	public void image3Botsclick(){
		createGameController.image3Botsclick();
	}
	public void image4Botsclick(){
		createGameController.image4Botsclick();
	}

	public CreateGameController getCreateGameController() {
		return createGameController;
	}

	@NiftyEventSubscriber(id="maplist")
	public void onMyListBoxSelectionChanged(final String id, final ListBoxSelectionChangedEvent<String> event){
		if(event.getSelection().size() > 0) {
			//System.out.println(event.getSelection().get(0));
			
			loadMapPreview(event.getSelection().get(0));
			setMapname(event.getSelection().get(0));
		}
	}
	
	public void kIJoin() {
		if ((screen.findNiftyControl("gamesBox",
				 ListBox.class).getFocusItem()) != null) {
					
					final String gameName = ((GameEntryModel) screen.findNiftyControl("gamesBox",
							ListBox.class).getFocusItem()).getName();

					final String status = ((GameEntryModel) screen.findNiftyControl("gamesBox",
							ListBox.class).getFocusItem()).getStatus();
					
					if (status.equals("RUNNING")) {
						return;
					}
					
					clear();
					
					gui.getStart().getModel().setView(false);
					gui.getStart().getModel().setGameName(gameName);
					gui.getStart().getConnection().sendMessage("create testplayer");
					
		}
				
	}
	
	public void setMapname(String mapname) {
		if(screen.findElementByName("Mapnametext") != null)
			screen.findElementByName("Mapnametext").getRenderer(TextRenderer.class).setText(mapname);
	}
	
	private void loadMapPreview(final String preview) {
		new Thread(new Runnable() { 
			@Override
			public void run() {
				if(!(gui.getStart().getConnection().getMessageReceiver() instanceof ConnectionHandler)) {
					return;
				}
				
				ConnectionHandler connectionHandler = (ConnectionHandler)gui.getStart().getConnection().getMessageReceiver();
				MapDownload mapDownload = connectionHandler.getMapDownload();
				
				mapDownload.downloadMap(preview);
				mapDownload.waitForDownload();
				
				gui.getLobbyScreen().setPreviewImage(mapDownload.getPicture());
				setMapname(preview);
			}
		}).start();
	}
	
	private void clear() {
		chatBox.clear();
		gameBoxController.deleteAll();
		playerBoxController.deleteAll();
	}
	
	public void showErrorPopup() {
		gui.getNifty().showPopup(gui.getNifty().getScreen("lobby"), errorPopup.getErrorPopup().getId(), null);
	}
	
	public void closeErrorPopup() {
		gui.getNifty().closePopup(errorPopup.getErrorPopup().getId());
	}
	
	public void setErrorOccured(boolean errorOccured) {
		this.errorOccured = errorOccured;
	}
	
	public boolean getErrorOccured () {
		return errorOccured;
	}
	//ENDE Festlegen der Panelclickactionen Image2Players/Image3Players/Image
}
//ENDE BOOOOOOOOOOOOTS